﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.StorageManagers.DataSetStorage;
using DomainDriver.DomainModeling.StorageManagers.EntityFrameworkStorage;
using AutomotivePricingModel.ValueObjects.MissingValueOptions;
using ObjectRow = AutomotivePricingModel.ValueObjects.YearlyFinancialAssessments.YearlyFinancialAssessmentsDataSet.YearlyFinancialAssessmentsRow;
using NestedObjectRow = AutomotivePricingModel.ValueObjects.YearlyFinancialAssessments.YearlyFinancialAssessmentsDataSet.YearValueObservationsRow;

namespace AutomotivePricingModel.ValueObjects.YearlyFinancialAssessments
{
    public partial class YearlyFinancialAssessment : IDataSetSerializable<DataSet, DataRow>
    {
        #region ADO .NET Entities Framework Storage

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid EF_YearlyFinancialAssessmentId
        {
            get { return m_Key; }
            set { m_Key = value; }
        }

        [Required]
        public int EF_MissingValueOption
        {
            get { return (int)m_MissingValueOption; }
            set { m_MissingValueOption = (MissingValueOptionEnum)value; }
        }

        //[Required]
        [NotMapped]
        public ICollection<YearValueObservation> EF_YearlyObservations
        {
            get
            {
                List<YearValueObservation> observations = new List<YearValueObservation>(m_YearlyObservations.Values);
                return observations;
            }
            set
            {
                m_YearlyObservations.Clear();
                foreach (YearValueObservation observation in value)
                {
                    m_YearlyObservations.Add(observation.Year, observation);
                }
            }
        }

        public static YearlyFinancialAssessment ReadValueObject(DbContext context, Guid assessmentId)
        {
            IQueryable<YearlyFinancialAssessment> assessmentResults = context.Set<YearlyFinancialAssessment>().Where<YearlyFinancialAssessment>((YearlyFinancialAssessment financialAssessment) => financialAssessment.EF_YearlyFinancialAssessmentId == assessmentId);
            if (assessmentResults.Count<YearlyFinancialAssessment>() < 0)
            { return null; }
            YearlyFinancialAssessment assessment = assessmentResults.First<YearlyFinancialAssessment>();

            IQueryable<YearValueObservation> observationResults = context.Set<YearValueObservation>().Where<YearValueObservation>((YearValueObservation observation) => observation.ParentYearlyFinancialAssessmentId == assessmentId);
            List<YearValueObservation> observationList = new List<YearValueObservation>(observationResults);
            assessment.EF_YearlyObservations = observationList;
            return assessment;
        }

        public static void AddValueObject(DbContext context, YearlyFinancialAssessment assessment)
        {
            context.Set<YearlyFinancialAssessment>().Add(assessment);

            Expression<Func<ICollection<YearValueObservation>>> nestedObjectsGetterExpression = () => assessment.EF_YearlyObservations;
            EfAggregateUtilities.AddNestedValues<YearValueObservation>(context, nestedObjectsGetterExpression);
        }

        public static void UpdateValueObject(DbContext context, YearlyFinancialAssessment updatedAssessment, YearlyFinancialAssessment originalAssessment)
        {
            Expression<Func<YearValueObservation, int>> keyGetterExpression = (YearValueObservation nestedObj) => nestedObj.Year;
            Expression<Func<YearValueObservation, YearValueObservation, bool>> nestedObjectsMatchExpression = (YearValueObservation obj1, YearValueObservation obj2) => ((obj1.ParentYearlyFinancialAssessmentId == obj2.ParentYearlyFinancialAssessmentId) && (obj1.Year == obj2.Year));
            Expression<Func<YearlyFinancialAssessment, IDictionary<int, YearValueObservation>>> dictionaryGetterExpression = (YearlyFinancialAssessment agg) => agg.m_YearlyObservations;
            EfAggregateUtilities.UpdateNestedValues<YearlyFinancialAssessment, int, YearValueObservation>(context, updatedAssessment, originalAssessment, keyGetterExpression, nestedObjectsMatchExpression, dictionaryGetterExpression);
        }

        public static void DeleteValueObject(DbContext context, YearlyFinancialAssessment assessment)
        {
            Expression<Func<YearValueObservation, bool>> yvoDeleteQueryExpression = ((YearValueObservation yvo) => (yvo.ParentYearlyFinancialAssessmentId == assessment.Key));
            EfAggregateUtilities.DeleteNestedValues(context, yvoDeleteQueryExpression);

            Expression<Func<YearlyFinancialAssessment, bool>> yfaDeleteQueryExpression = ((YearlyFinancialAssessment yfa) => (yfa.EF_YearlyFinancialAssessmentId == assessment.Key));
            EfAggregateUtilities.DeleteNestedValues(context, yfaDeleteQueryExpression);
        }

        #endregion

        #region AutomotivePricingDataSet Serialization

        public string ObjectTableName
        {
            get { return YearlyFinancialAssessmentsDataSet.SchemaHelper.YearlyFinancialAssessments.TableName; }
        }

        public string KeyColumnName
        {
            get { return YearlyFinancialAssessmentsDataSet.SchemaHelper.YearlyFinancialAssessments.YearlyFinancialAssessmentIdColumn.ColumnName; }
        }

        private string MissingValueOptionColumnName
        {
            get { return YearlyFinancialAssessmentsDataSet.SchemaHelper.YearlyFinancialAssessments.MissingValueOptionIdColumn.ColumnName; }
        }

        private string ObservationTableName
        {
            get { return YearlyFinancialAssessmentsDataSet.SchemaHelper.YearValueObservations.TableName; }
        }

        private string ParentIdColumnName
        {
            get { return YearlyFinancialAssessmentsDataSet.SchemaHelper.YearValueObservations.ParentIdColumn.ColumnName; }
        }

        public void Serialize(DataSet dataSet, DataRow dataRow)
        {
            dataRow[KeyColumnName] = m_Key;
            dataRow[MissingValueOptionColumnName] = (int)m_MissingValueOption;
            dataSet.Tables[ObjectTableName].Rows.Add(dataRow);

            DataTable observationDataTable = dataSet.Tables[ObservationTableName];
            foreach (YearValueObservation observation in m_YearlyObservations.Values)
            {
                DataRow observationDataRow = observationDataTable.NewRow();
                observation.Serialize(dataSet, observationDataRow);
            }
        }

        public void Deserialize(DataSet dataSet, DataRow dataRow)
        {
            m_Key = (Guid)dataRow[KeyColumnName];
            m_MissingValueOption = (MissingValueOptionEnum)dataRow[MissingValueOptionColumnName];

            m_YearlyObservations.Clear();
            DataTable observationDataTable = dataSet.Tables[ObservationTableName];
            string queryExpression = string.Format("{0} = '{1}'", ParentIdColumnName, m_Key);
            foreach (DataRow observationDataRow in observationDataTable.Select(queryExpression))
            {
                YearValueObservation observation = new YearValueObservation();
                observation.Deserialize(dataSet, observationDataRow);
                m_YearlyObservations.Add(observation.Year, observation);
            }
        }

        #endregion
    }
}